/*
 * 
 * LegendShop 多用户商城系统
 * 
 *  版权所有,并保留所有权利。
 * 
 */
package com.legendshop.oa.security.admin;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import com.legendshop.oa.exception.IPFormatException;
import com.legendshop.util.AppUtils;

/**
 * @Description 
 * @author 关开发
 */
public class IPAdminDaoAuthenticationProvider extends AdminDaoAuthenticationProvider {

	private Set<String> allowRegexList = new TreeSet<String>(new Comparator<String>(){

		@Override
		public int compare(String o1, String o2) {
			
			return 1;
		}
		
	});
	
	{
		initAllowRegexList();
	}
	
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails, Authentication authentication)
			throws AuthenticationException {
		super.additionalAuthenticationChecks(userDetails, authentication);
		
/*		//如果为空才初始化
		if(AppUtils.isBlank(allowRegexList)){
			initAllowRegexList();
		}*/
		
		String remoteAddr = null;
		
		Object object = authentication.getDetails();
		if(object instanceof WebAuthenticationDetails){
			WebAuthenticationDetails webDetails = (WebAuthenticationDetails) object;
			
			remoteAddr = webDetails.getRemoteAddress();
		}
		
		if(AppUtils.isBlank(remoteAddr)){
			throw new BadCredentialsException("IP地址为空,拒绝访问!");
		}
		
		if(AppUtils.isBlank(allowRegexList)){
			return;
		}
		
		if(!checkIp(remoteAddr,allowRegexList)){
			throw new BadCredentialsException("您的IP: "+remoteAddr+",不在白名单中,拒绝访问!");
		}
	}
	
	public boolean checkIp(String remoteAddr,Set<String> allowRegexList){
		
		for(String regex : allowRegexList){
			if(remoteAddr.matches(regex)){
				return true;
			}
		}
		
		return false;
	}
	
	public void initAllowRegexList(){
		
//		String allowIP = EnvironmentConfig.getInstance().getPropertyValue(FileConfig.ConfigFile, "ALLOW_IP");
//		String allowIPRange = EnvironmentConfig.getInstance().getPropertyValue(FileConfig.ConfigFile, "ALLOW_IP_RANGE");
//		String allowIPWildcard = EnvironmentConfig.getInstance().getPropertyValue(FileConfig.ConfigFile, "ALLOW_IP_WILDCARD");
		
		//TODO need to change it
		String allowIP ="127.0.0.1";
		String allowIPRange ="";
		String allowIPWildcard = "";
		
		if(!validate(allowIP, allowIPRange, allowIPWildcard)){
			throw new IPFormatException("IP白名单格式定义异常!");
		}
		
		if(AppUtils.isNotBlank(allowIP)){
			String[] address = allowIP.split(",|;");
			
			if(null != address && address.length > 0){
				for(String ip : address){
					allowRegexList.add(ip);
				}
			}
		}
		
		if(AppUtils.isNotBlank(allowIPRange)){
			String[] addressRanges = allowIPRange.split(",|;");
			
			if(null != addressRanges && addressRanges.length > 0){
				for(String addrRange : addressRanges){
					String[] addrParts = addrRange.split("-");
					
					if(null != addrParts && addrParts.length >0 
							&& addrParts.length <= 2){
						String from = addrParts[0];
						String to = addrParts[1];
						String prefix = from.substring(0, from.lastIndexOf(".")+1);
						
						int start = 
								Integer.parseInt(
											from.substring(
												from.lastIndexOf(".")+1,
												from.length()
											)
										);
						int end = Integer.parseInt(
											to.substring(
												to.lastIndexOf(".")+1,
												to.length()
											)
										  );
						
						for(int i = start;i <= end;i++){
							allowRegexList.add(prefix+i);
						}
						
					}else{
						throw new IPFormatException("IP列表格式定义异常!");
					}
				}
			}
		}
		
		if(AppUtils.isNotBlank(allowIPWildcard)){
			String[] address = allowIPWildcard.split(",|;");
			
			if(null != address && address.length > 0){
				for(String addr : address){
					if(addr.indexOf("*") != -1){
						addr = addr.replaceAll("\\*", "(1\\\\d{1,2}|2[0-4]\\\\d|25[0-5]|\\\\d{1,2})");
						addr = addr.replaceAll("\\.", "\\\\.");
						
						allowRegexList.add(addr);
					}else{
						throw new IPFormatException("IP白名单格式定义异常!");
					}
				}
			}
		}
	}
	
	public boolean validate(String allowIP,
			String allowIPRange,
			String allowIPWildcard){
		
		String regx = "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})";
		String ipRegx = regx + "\\." + regx + "\\."+ regx + "\\." + regx;
	    
	    Pattern pattern = Pattern.compile("("+ipRegx+")|("+ipRegx+"(,|;))*");
	    
	    if(!this.validate(allowIP, pattern)){
	    	return false;
	    }
		    
		
	    pattern = Pattern.compile("("+ipRegx+")\\-("+ipRegx+")|"
	                    + "(("+ipRegx+")\\-("+ipRegx+")(,|;))*");
	    
	    if(!this.validate(allowIPRange, pattern)){
	    	return false;
	    }
		
	    pattern = Pattern.compile("("+regx+"\\."+ regx+"\\."+regx+"\\."+ "\\*)|"
	                    +"("+regx+"\\."+regx+"\\."+regx+"\\."+ "\\*(,|;))*");
		
	    if(!this.validate(allowIPWildcard, pattern)){
	    	return false;
	    }
		
		return true;
	}
	
	public boolean validate(String allowIP,Pattern pattern){
		if(AppUtils.isNotBlank(allowIP)){
		    StringBuilder sb = new StringBuilder(allowIP);
		    
		    if(!allowIP.endsWith(";")){
		    	sb.append(";");
		    }
		    
		    if(!pattern.matcher(sb).matches()){
		    	return false;
		    }
		}
		return true;
	}
}
